package com.ml.mall.service.company.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ml.mall.bean.req.company.CompanyRelationAddDto;
import com.ml.mall.bean.req.company.CompanyRelationDelDto;
import com.ml.mall.bean.req.company.CompanyRelationEditDto;
import com.ml.mall.bean.req.company.UCChangeCompanyDto;
import com.ml.mall.bean.req.sys.SysUserDto;
import com.ml.mall.bean.vo.sys.SysUserCompanyRelationVo;
import com.ml.mall.consts.CommonConsts;
import com.ml.mall.entity.company.SysCompany;
import com.ml.mall.entity.company.SysUserCompanyRelation;
import com.ml.mall.entity.sys.SysRole;
import com.ml.mall.entity.sys.SysSubscription;
import com.ml.mall.entity.sys.SysUser;
import com.ml.mall.enums.CommonEnum;
import com.ml.mall.enums.RedisUtilsCacheEnum;
import com.ml.mall.exception.BizException;
import com.ml.mall.mapper.company.SysCompanyMapper;
import com.ml.mall.mapper.company.SysUserCompanyRelationMapper;
import com.ml.mall.mapper.sys.SysUserMapper;
import com.ml.mall.security.JwtUtil;
import com.ml.mall.service.asyn.AuthMailServiceImplAsyn;
import com.ml.mall.service.company.SysUserCompanyRelationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ml.mall.service.sys.ISysRoleService;
import com.ml.mall.service.sys.SysSubscriptionService;
import com.ml.mall.service.sys.SysUserService;
import com.ml.mall.utils.RedisUtil;
import com.ml.mall.utils.UserCompanyRelationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
* <p>
    *  服务实现类
    * </p>
*
* @author pl
* Created 2021-06-15
*/
@Service
@Slf4j
public class SysUserCompanyRelationServiceImpl extends ServiceImpl<SysUserCompanyRelationMapper, SysUserCompanyRelation> implements SysUserCompanyRelationService {

    @Autowired
    private  SysUserCompanyRelationMapper  sysUserCompanyRelationMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysCompanyMapper sysCompanyMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SysUserService sysUserService;

    @Lazy
    @Autowired
    private AuthMailServiceImplAsyn authMailServiceImplAsyn;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private SysSubscriptionService sysSubscriptionService;

    @Override
    public int addUserCompany(CompanyRelationAddDto dto) {

        SysUser user = JwtUtil.getCurrentUser();
        //获取绑定的companyId：
        Long boundCompanyId = 0L;
        String boundAcc = null;

        if(CommonConsts.ROLE_TYPE_ADMIN.equals(user.getRoleType())){
            boundCompanyId = dto.getCompanyId();
            boundAcc = dto.getAcc();
        }else{
            boundCompanyId = user.getCompanyId();
            boundAcc = user.getAcc();
        }

        //公司添加的用户,角色类型需要与公司类型相对应
        SysCompany dbCompany = sysCompanyMapper.selectByCompanyId(dto.getCompanyId());

        //禁止为非正常状态的公司创建用户
        if(!CommonConsts.STATE_NORMAL.equals(dbCompany.getState())){
            throw new BizException(CommonEnum.COMPANY_STATE_ABNORMAL);
        }

        checkRoleId(dto.getRoleId(),dbCompany);

        //进行redis的添加,获取key值
        String userCompanyRelationKey = RedisUtilsCacheEnum.REDIS_KEY_USER_COMPANY_RELATION.getKeyPrefix() + UserCompanyRelationUtil.getCurUserCompanyRelationKey();
        //公司添加用户；判断是创建缓存还是创建user_company_relation
        //1.首先通过sys_user判断当前账号是否存在
        SysUser dbUser = sysUserMapper.selectByAccount(dto.getAcc());
        //对应的公司信息 todo:daizh 修改为公司查询


        //判断公司用户数是否达到限制
        Integer userCount = sysUserCompanyRelationMapper.countByCompanyId(dto.getCompanyId());
        SysSubscription subscription = sysSubscriptionService.getById(dbCompany.getSubType());
        if (CommonConsts.ROLE_TYPE_PURCHASE.equals(dbCompany.getCompanyType()) || CommonConsts.ROLE_TYPE_SUPPLIER.equals(dbCompany.getCompanyType())) {
            if (userCount >= subscription.getLimitUserNum()) {
                throw new BizException(CommonEnum.COMPANY_USER_NUM_REACHED_MAXIMUM);
            }
        }

        if (null != dbUser){
            //判断已存在的用户的角色类型与当前公司的角色类型是否一致
            if(!dbUser.getRoleType().equals(dbCompany.getCompanyType())){
                throw new BizException(CommonEnum.COMPANY_USER_ROLE_TYPE_ERROR);
            }

            QueryWrapper<SysUserCompanyRelation> ifHaveAccWrapper = new QueryWrapper<>();
            ifHaveAccWrapper.eq("acc",dto.getAcc());
            ifHaveAccWrapper.eq("company_id",dto.getCompanyId());
            //判断sys_company_relation表中当前Acc是否已经存在
            Integer isHaveRelation = sysUserCompanyRelationMapper.selectCount(ifHaveAccWrapper);
            //对应公司存在该账号；异常
            if (isHaveRelation !=0 ){
                throw new BizException(CommonEnum.ALREADY_EXIST_SAME);
            }
            //对应公司不存在关联，新建关联
            SysUserCompanyRelation saveToDB = new SysUserCompanyRelation();
            saveToDB.setAcc(dto.getAcc())
                .setCompanyId(dbCompany.getCompanyId())
                .setCompanyName(dbCompany.getCompanyName())
                .setRoleId(dto.getRoleId());
            int insert = sysUserCompanyRelationMapper.insert(saveToDB);


            if (insert==0){
                throw new BizException(CommonEnum.INSERT_ERROR);
            }
        } else {
            //user 添加用户
            SysUserDto sysUserDto = new SysUserDto();
            BeanUtils.copyProperties(dto, sysUserDto);
            sysUserDto.setRoleType(dbCompany.getCompanyType());
            sysUserDto.setPwd(CommonConsts.DEFAULT_PWD);
            sysUserService.save(sysUserDto);

            //给新用户发送邮件
            authMailServiceImplAsyn.userSaveMailAsyn(sysUserDto);

            boolean ifHasParams = redisUtil.hasKey(userCompanyRelationKey);
            if (ifHasParams){
                long redisDataSize = redisUtil.lGetListSize(userCompanyRelationKey);
                //从redis中获取已存在数据信息
                List<Object> queryNeedRedisData = redisUtil.lGet(userCompanyRelationKey, 0, redisDataSize-1);
                for (Object item:queryNeedRedisData){
                    CompanyRelationAddDto getCompanyRelationFromRedis = JSON.parseObject((String) item, CompanyRelationAddDto.class);
                    if (getCompanyRelationFromRedis.getAcc().equals(dto.getAcc())){
                        throw new BizException(CommonEnum.ALREADY_EXIST_SAME);
                    }
                }
                //redis中不存在一样的账号
                SysUserCompanyRelationVo getRoleTypeCompanyNameCompanyId = sysUserCompanyRelationMapper.selectUserAndCompanyToSave(boundCompanyId,boundAcc);
                SysUserCompanyRelation saveToDB = new SysUserCompanyRelation();
                saveToDB.setAcc(dto.getAcc())
                    .setCompanyName(getRoleTypeCompanyNameCompanyId.getCompanyName())
                    .setRoleId(dto.getRoleId());
                saveToDB.setCompanyId(boundCompanyId);
                int insert = sysUserCompanyRelationMapper.insert(saveToDB);
                if (insert==0){
                    throw new BizException(CommonEnum.INSERT_ERROR);
                }
            }

            //将传入信息存入redis
            String needSaveRedis = JSONObject.toJSONString(dto);
            redisUtil.lSet(userCompanyRelationKey,needSaveRedis);
        }
        return 1;
    }

    @Override
    @Transactional
    public void delUserCompany(CompanyRelationDelDto dto) {
        //删除用户信息
        LambdaQueryWrapper<SysUser> userQueryWrapper = new LambdaQueryWrapper<>();
        userQueryWrapper.eq(SysUser::getAcc, dto.getAcc());
        int deleteFlag = sysUserMapper.delete(userQueryWrapper);
        if(deleteFlag == 0){
            throw new BizException(CommonEnum.DELETE_ERROR);
        }

        //删除关联信息
        LambdaQueryWrapper<SysUserCompanyRelation> wrapper  = new LambdaQueryWrapper<>();
        wrapper.eq(SysUserCompanyRelation::getAcc,dto.getAcc());
        wrapper.eq(SysUserCompanyRelation::getCompanyId,dto.getCompanyId());
        deleteFlag = sysUserCompanyRelationMapper.delete(wrapper);

        if(deleteFlag == 0){
            throw new BizException(CommonEnum.DELETE_ERROR);
        }
    }

    @Override
    public List<SysUserCompanyRelation> getCompanyQueryUser(CompanyRelationAddDto dto) {
        QueryWrapper<SysUserCompanyRelation> wrapper  = new QueryWrapper<>();
        wrapper.eq("acc",dto.getAcc());
        List<SysUserCompanyRelation> sysUserCompanyRelations = sysUserCompanyRelationMapper.selectList(wrapper);
        return sysUserCompanyRelations;
    }

    @Override
    @Transactional
    public void editUserCompany(CompanyRelationEditDto dto) {
        //用户类型需要与公司类型一致
        Long companyId = dto.getCompanyId();
        //非管理员用户只能修改本公司用户信息
        SysUser currentUser = JwtUtil.getCurrentUser();
        if(!CommonConsts.ROLE_TYPE_ADMIN.equals(currentUser.getRoleType())){
            dto.setCompanyId(currentUser.getCompanyId());
            //用户不属于该公司时，返回错误信息
            SysUser dbUser = sysUserMapper.selectByAccount(dto.getAcc());
            if(dbUser.getCompanyId() == null || !dbUser.getCompanyId().equals(dto.getCompanyId())){
                throw new BizException(CommonEnum.NO_ASSOCIATION_BETWEEN_COMPANY_AND_USER);
            }
            checkRoleId(dto.getRoleId(), sysCompanyMapper.selectByCompanyId(companyId));
        }
        //修改用户信息
        LambdaUpdateWrapper<SysUser> userUpdateWrapper = new LambdaUpdateWrapper<>();
        userUpdateWrapper.set(dto.getName() != null, SysUser::getName, dto.getName())
                         .set(dto.getLastName() != null, SysUser::getLastName, dto.getLastName())
                         .set(dto.getEmail() != null, SysUser::getEmail, dto.getEmail())
                         .set(dto.getRoleId() != null, SysUser::getRoleId, dto.getRoleId())
                         .set(dto.getState() != null, SysUser::getState, dto.getState())
                         .eq(SysUser::getAcc, dto.getAcc());
        log.info("sysUser==222222222222==");
        int i = sysUserMapper.update(null, userUpdateWrapper);
        if(i == 0){
            throw new BizException(CommonEnum.UPDATE_ERROR);
        }

        //修改关联信息
        LambdaUpdateWrapper<SysUserCompanyRelation> relationUpdateWrapper = new LambdaUpdateWrapper<>();
        relationUpdateWrapper.set(SysUserCompanyRelation::getRoleId, dto.getRoleId())
                             .eq(SysUserCompanyRelation::getAcc, dto.getAcc())
                             .eq(SysUserCompanyRelation::getCompanyId, companyId);
        sysUserCompanyRelationMapper.update(null ,relationUpdateWrapper);
    }

    @Override
    public List<SysUserCompanyRelation> selfUCRelationQuery() {
        SysUser currentUser = JwtUtil.getCurrentUser();
        return sysUserCompanyRelationMapper.selectByAcc(currentUser.getAcc());
    }

    @Override
    public boolean changeCompany(UCChangeCompanyDto dto) {
        SysUser currentUser = JwtUtil.getCurrentUser();

        //获取当前用户的对应公司关联信息
        LambdaQueryWrapper<SysUserCompanyRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserCompanyRelation::getAcc, currentUser.getAcc())
                    .eq(SysUserCompanyRelation::getCompanyId, dto.getCompanyId());
        SysUserCompanyRelation userCompanyRelation = getOne(queryWrapper);

        //判断公司与用户是否存在关联
        if(null == userCompanyRelation){
            throw new BizException(CommonEnum.NO_ASSOCIATION_BETWEEN_COMPANY_AND_USER);
        }

        //判断公司状态是否正常
        SysCompany sysCompany = sysCompanyMapper.selectByCompanyId(dto.getCompanyId());
        if(sysCompany == null || !CommonConsts.STATE_NORMAL.equals(sysCompany.getState())){
            throw new BizException(CommonEnum.COMPANY_STATE_ABNORMAL);
        }

        //查询对应的角色信息
        SysRole sysRole = roleService.getById(userCompanyRelation.getRoleId());

        //根据公司关联信息修改用户信息
        currentUser.setCompanyId(userCompanyRelation.getCompanyId())
                   .setRoleId(sysRole.getId())
                   .setRoleType(sysRole.getRoleType());
        return sysUserService.updateById(currentUser);
    }

    @Override
    public boolean addUCRelation(SysUser sysUser, SysCompany dbCompany) {
        SysUserCompanyRelation userCompanyRelation = new SysUserCompanyRelation();
        userCompanyRelation.setAcc(sysUser.getAcc())
                           .setRoleId(sysUser.getRoleId())
                           .setCompanyId(dbCompany.getCompanyId())
                           .setCompanyName(dbCompany.getCompanyName());
        return save(userCompanyRelation);
    }

    /**
     * 检查roleId是否与公司类型相匹配
     * @param roleId
     * @param sysCompany
     */
    private void checkRoleId(Integer roleId, SysCompany sysCompany) {
        if(null == sysCompany){
            throw new BizException(CommonEnum.COMPANY_IS_NOT_EXIST);
        }
        LambdaQueryWrapper<SysRole> roleQueryWrapper = new LambdaQueryWrapper<>();
        roleQueryWrapper.eq(SysRole::getRoleType, sysCompany.getCompanyType())
                .select(SysRole::getId);
        List<SysRole> roles = roleService.list(roleQueryWrapper);
        List<Integer> roleIds = roles.stream()
                .map(SysRole::getId)
                .collect(Collectors.toList());
        if(!roleIds.contains(roleId)){
            throw new BizException(CommonEnum.COMPANY_USER_ROLE_ERROR);
        }
    }
}
